#wxGNAPEntry
#Derived from wxSurvivalEntry
#
#Implements gNAP style input into the wxgrid.
 
use Wx 0.15 qw[:allclasses];
use strict;

package wxGNAPEntry;
use base qw(wxSurvivalEntry);
use Wx qw[:everything];


#Constructor
sub new {
    my $self = shift;
    $self = $self->SUPER::new( @_ );

	
	#buttons for selecting all / none / invert
	$self->{panel_select} = Wx::Panel->new($self->{panel_grid}, -1, wxDefaultPosition, wxDefaultSize);
	#Label for select buttons
	$self->{button_select_all} = Wx::Button->new($self->{panel_select}, -1, "All", wxDefaultPosition, wxDefaultSize);
	$self->{button_select_none} = Wx::Button->new($self->{panel_select}, -1, "None", wxDefaultPosition, wxDefaultSize);
	$self->{button_select_invert} = Wx::Button->new($self->{panel_select}, -1, "Invert", wxDefaultPosition, wxDefaultSize);
	#button for adding/removing points
	$self->{panel_points} = Wx::Panel->new($self->{panel_grid}, -1, wxDefaultPosition, wxDefaultSize);
	$self->{button_point_add} = Wx::Button->new($self->{panel_points}, wxID_ADD, "");
	$self->{button_point_remove} = Wx::Button->new($self->{panel_points}, wxID_REMOVE, '');

	#Do the layout
	$self->{sizer_buttons} = Wx::BoxSizer->new(wxHORIZONTAL);
	$self->{box_select} = Wx::StaticBox->new($self->{panel_select}, -1, 'Select');
	$self->{box_points} = Wx::StaticBox->new($self->{panel_points}, -1, 'Points');

	$self->{sizer_buttons_select} = Wx::StaticBoxSizer->new($self->{box_select}, wxHORIZONTAL);
	$self->{sizer_buttons_points} = Wx::StaticBoxSizer->new($self->{box_points}, wxHORIZONTAL);
	$self->{sizer}->Add($self->{sizer_buttons}, 0,  wxCENTER|wxEXPAND);
	$self->{sizer_buttons}->Add($self->{panel_select}, 0,  wxALIGN_LEFT|wxEXPAND|wxLEFT|wxTOP|wxBOTTOM,2);
	$self->{sizer_buttons}->AddStretchSpacer(1);
	$self->{sizer_buttons}->Add($self->{panel_points}, 0,  wxALIGN_RIGHT|wxEXPAND|wxRIGHT|wxTOP|wxBOTTOM,2);
	$self->{panel_select}->SetSizer($self->{sizer_buttons_select});
	$self->{panel_points}->SetSizer($self->{sizer_buttons_points});
	
	$self->{sizer_buttons_select}->Add($self->{button_select_all}, 0,  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
	$self->{sizer_buttons_select}->Add($self->{button_select_none}, 0, wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);
	$self->{sizer_buttons_select}->Add($self->{button_select_invert}, 0,  wxALIGN_LEFT|wxALIGN_CENTER_VERTICAL);

	
	$self->{sizer_buttons_points}->Add($self->{button_point_add}, 0,  wxALIGN_CENTER_VERTICAL);
	$self->{sizer_buttons_points}->Add($self->{button_point_remove}, 0,  wxALIGN_CENTER_VERTICAL);

	$self->Layout();	

	#Register events
#	Wx::Event::EVT_GRID_CELL_CHANGE($self, \&set_survival);
	Wx::Event::EVT_BUTTON($self, $self->{button_select_all}->GetId, \&select_all);
	Wx::Event::EVT_BUTTON($self, $self->{button_select_none}->GetId, \&select_none);
	Wx::Event::EVT_BUTTON($self, $self->{button_select_invert}->GetId, \&select_invert);
	Wx::Event::EVT_BUTTON($self, $self->{button_point_add}->GetId, \&add_point);
	Wx::Event::EVT_BUTTON($self, $self->{button_point_remove}->GetId, \&remove_point);
	Wx::Event::EVT_GRID_CELL_CHANGE($self, \&set_survival);
	Wx::Event::EVT_GRID_SELECT_CELL($self, \&select_cell_replot);
	Wx::Event::EVT_SPLITTER_SASH_POS_CHANGED($self, $self->GetId, \&set_splitter_position); 
	Wx::Event::EVT_SPLITTER_SASH_POS_CHANGING($self, $self->GetId, \&set_splitter_position); 
	
	#$self->SetSashPosition($self->{sizer_buttons}->GetMinSize()->GetWidth(),1);
    return $self;
}


#Sets the sash position to the minimum value, or if triggered
#by a sash position change it enforces the minimum value
sub set_splitter_position {
	my ($self, $event) = @_;
	
	my $proposed;
	if (defined $event) {
		$proposed = $event->GetSashPosition();
	} else {
		$proposed = $self->GetSashPosition();
	}
	
	my $minimum = $self->{sizer_buttons}->GetMinSize()->GetWidth();
	my $width = $self->GetSize()->GetWidth();
	my $maximum = $width - 50;
	
	if ($proposed > $maximum) {
		$proposed = $maximum;
	}
	if ($proposed < $minimum) {
		$proposed = $minimum;
	}
	if ($proposed > $width) {
		$proposed = $width-10;
	}
	if (defined $event) {
		$event->SetSashPosition($proposed);
		$event->Skip();
	} else {
		$self->SetSashPosition($proposed);
	}
}

#Add the GNAP specific rows
sub blank_grid {
	my $self = shift;
	$self->SUPER::blank_grid();
	$self->insert_row('Survival Prob.');
	$self->insert_row('Cost');
	#Disable cost/prob cells for the plot column
	$self->enable_cell(0,0,0);
	$self->enable_cell(1,0,0);
	#Set the point ID counter
	$self->{point_id} = 1;
	
}	

#Add a new point
sub add_point {
	my ($self,$event) = @_;
	$self->insert_col('Point '.$self->{point_id}, $self->{grid}->GetNumberCols()-1);
	$self->{point_id}++;
	
	#Make all species selectors boolean
	for (my $row = 2; $row < $self->{grid}->GetNumberRows(); $row++) {
		$self->make_cell_bool($row,$self->{grid}->GetNumberCols()-2,1);
	}
	if (defined $event) {$event->Skip();}
	$self->set_max_size();
	
}

#Remove a point
sub remove_point {
	my ($self, $event) = @_;
	my $col = $self->{grid}->GetGridCursorCol();

	#If a column is selected and it is not the plot column
	if (defined $col && $col < $self->{grid}->GetNumberCols() - 1 ) {
		my @col_labels;
		#Store old column labels
		for (my $index = 0; $index < $self->{grid}->GetNumberCols(); $index++) {
			unless($index == $col) { push(@col_labels, $self->{grid}->GetColLabelValue($index)); }
		}
		#Delete column
		$self->{grid}->DeleteCols($col,1,0);
		#Relabel columns
		for (my $index = 0; $index < $self->{grid}->GetNumberCols(); $index++) {
			$self->{grid}->SetColLabelValue($index, $col_labels[$index]); 
		}
		$self->set_survival();	
	}
	if (defined $event) {$event->Skip();}
}

#Select all check boxes
sub select_all {
	my ($self, $event) = @_;
	$self->toggle_bools('all');
	if (defined $event) {$event->Skip();}
}

#Deselect all check boxes
sub select_none {
	my ($self, $event) = @_;
	$self->toggle_bools('none');
	if (defined $event) {$event->Skip();}
}

#Invert the check box selection
sub select_invert {
	my ($self, $event) = @_;
	$self->toggle_bools('invert');
	if (defined $event) {$event->Skip();}
}

#Toggle the check box selection according to the input argument 
#('all', 'none' or 'invert')
sub toggle_bools {
	my ($self, $type) = @_;
	
	my $col = $self->{grid}->GetGridCursorCol();
	unless (defined $col) { return; }
	
	my $changed = 0;
	for (my $row = 2; $row < $self->{grid}->GetNumberRows(); $row++) {
		my $bool_value = $self->{grid}->GetCellValue($row,$col);
		my $new_value;
		if ($type eq 'all') { $new_value = '1'; }
		if ($type eq 'none') { $new_value = '0'; }
		if ($type eq 'invert') { $new_value = !$bool_value; }
		$changed = $changed || !($bool_value eq $new_value);
		$self->{grid}->SetCellValue($row,$col,$new_value); 
	}
	print $changed;
	#If the selection has changed
	if ($changed) {
		#New set of species to plot
		if ($col == $self->{grid}->GetNumberCols()-1) {
			$self->update_plot_selection();
			#Plot the changed object
			$self->plot_survival();
		#New data			
		} else {
			#Set the survival object (automatically replots)
			$self->set_survival();
		}
	}
}

#Check whether a cell is a boolean value (any column, but not first two rows)
sub is_bool {
	my ($self, $row, $col) = @_;
	
	unless (defined $row && defined $col) { return 0; }
	if ($row > 1) { return 1;}
	
	return 0;
}

#Fill the grid from the survival object
sub fill_grid {
	
}

#Set the survival object from the grid
sub set_survival {
	my ($self, $event) = @_;

	$self->{state}->{survival_gnap}->set_survivalprobabilities_blank();

	for (my $col = 0; $col < $self->{grid}->GetNumberCols()-1; $col++) {
		my $cost = $self->{grid}->GetCellValue(0,$col);
		my $survival = $self->{grid}->GetCellValue(1,$col);
		my @species;
		for (my $row = 2; $row < $self->{grid}->GetNumberRows(); $row++) {
			if ($self->{grid}->GetCellValue($row,$col)) {
				push(@species, $self->{grid}->GetRowLabelValue($row));
			}
		}
		$self->{state}->{survival_gnap}->add_point(@species, $cost, $survival);
	}		
	
	if (defined $event) {$event->Skip();}
	$self->plot_survival();
}

#a click on a bool does not cause a cell change event so if a cell is clicked we call set_survival here after everything else is handled
sub select_cell_replot {
	my ($self, $event) = @_;
	$event->Skip();
	$self->set_survival();
}
1;